package com.itheima.health.service.impl;


import com.itheima.health.dao.MemberDao;
import com.itheima.health.dao.OrderDao;
import com.itheima.health.pojo.HotSetmeal;
import com.itheima.health.pojo.Order;
import com.itheima.health.pojo.Setmeal;
import com.itheima.health.service.ReportService;
import com.itheima.health.vo.SetmealReportParam;
import com.itheima.health.vo.GetMemberReportVO;
import com.itheima.health.vo.ReportDataVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.*;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.List;

/**
 * 数据报表service
 */
@Service
@Slf4j
public class ReportServiceImpl implements ReportService {
    @Autowired
    private MemberDao memberDao;
    @Autowired
    private OrderDao orderDao;


    @Override
    public List<String> getSetmealNames() {
        List<SetmealReportParam> setmealReportParamList = orderDao.getSetmealReport();
        List<String> setmealNames = new ArrayList<>();
        for (SetmealReportParam setmealReportParam : setmealReportParamList) {
            setmealNames.add(setmealReportParam.getName());
        }
        return setmealNames;
    }

    @Override
    public List<SetmealReportParam> getSetmealCount() {
        List<SetmealReportParam> setmealReportParamList = orderDao.getSetmealReport();
        return setmealReportParamList;
    }
    /**
     * 获取会员统计信息
     * @return
     */
    @Transactional
   @Scheduled(cron = "0 0 0 1 * *")
    @Override
    public GetMemberReportVO getMemberReport() {
//        先获取当前时间
        LocalDate now = LocalDate.now();
//        减去一年
        LocalDate nowMinYear = now.minusYears(1);
//        创建返回月份集合
        List<String> months = new ArrayList<>();
//        创建返回会员数集合
        List<Long> memeberCount = new ArrayList<>();
        for (int i = 1; i <= 12; i++) {
//            再每次加一个月
            LocalDate plusMonth = nowMinYear.plusMonths(i);

//            获取本月第一天
            LocalDate monthFirst = plusMonth.of(plusMonth.getYear(), plusMonth.getMonth(), 1);
//            获取本月最后一天
            LocalDate monthEnd = monthFirst.plusMonths(1).minusDays(1);

//          查询符合条件的数量
            if (i==1){
                //查询第一个月
                Long count = memberDao.selectFirstMonth(monthEnd);
                memeberCount.add(count);
            }else if (i==12){
//                查询最后一个月
                Long count = memberDao.selectEndMonth(now);
                memeberCount.add(count);
            }else {
//                其他月份查询
                Long count = memberDao.selectOther(monthEnd);
                memeberCount.add(count);
            }



//            转换成字符串
            String month = plusMonth.format(DateTimeFormatter.ofPattern("yyyy.MM"));
            months.add(month);

        }


        //返回结果
        GetMemberReportVO getMemberReportVO = new GetMemberReportVO();
        getMemberReportVO.setMemberCount(memeberCount);//返回会员数
        getMemberReportVO.setMonths(months);//返回月数
        return getMemberReportVO;
    }
    @Override
    public ReportDataVO getBusinessReportData() {
        //new一个响应数据对象
        ReportDataVO reportDataVO = new ReportDataVO();

        //今日日期
        LocalDate today = LocalDate.now();
        // 获取本周第一天
        LocalDate thisWeekFirstDay = today.with(DayOfWeek.MONDAY);
        //获取本月第一天
        LocalDate thisMonthFirstDay = today.with(TemporalAdjusters.firstDayOfMonth());

        //设置统计日期
        reportDataVO.setReportDate(LocalDate.now());
        //今日到诊数
        Long todayVisitsNumber = orderDao.selectTodayOrder(today,Order.ORDERSTATUS_YES);
        //本周到诊数
        Long thisWeekVisitsNumber = orderDao.selectThisOrder(today,thisWeekFirstDay,Order.ORDERSTATUS_YES);
        //本月到诊数
        Long thisMonthVisitsNumber = orderDao.selectThisOrder(today,thisMonthFirstDay,Order.ORDERSTATUS_YES);

        //今日预约数
        Long todayOrderNumber = orderDao.selectTodayOrder(today,null);
        //本周预约数
        Long thisWeekOrderNumber = orderDao.selectThisOrder(today,thisWeekFirstDay,null);
        //本月预约数
        Long thisMonthOrderNumber = orderDao.selectThisOrder(today,thisMonthFirstDay,null);
        //总预约数
        Long orderNumber = orderDao.selectOrderNumber();

        //今日新增会员数
        Long todayNewMember = memberDao.selectTodayNew(today);
        //本周新增会员数
        Long thisWeekNewMember = memberDao.selectThisNew(today,thisWeekFirstDay);
        //本月新增会员数
        Long thisMonthNewMember = memberDao.selectThisNew(today,thisMonthFirstDay);
        //会员总数
        Long totalMember = memberDao.selectTotal();

        //热门套餐
        List<HotSetmeal> hotSetmeals = memberDao.selectHotSetmeals();

        //封装进预约占比数据
        for (HotSetmeal hotSetmeal : hotSetmeals) {
            String proportion = String.format("%.2f", hotSetmeal.getSetmeal_count().doubleValue()/orderNumber*100)+"%";

            hotSetmeal.setProportion(proportion);
        }

        //将数据封装到对象中
        reportDataVO.setReportDate(today);
        reportDataVO.setTodayVisitsNumber(todayVisitsNumber);
        reportDataVO.setThisWeekVisitsNumber(thisWeekVisitsNumber);
        reportDataVO.setThisMonthVisitsNumber(thisMonthVisitsNumber);
        reportDataVO.setTodayNewMember(todayNewMember);
        reportDataVO.setThisWeekNewMember(thisWeekNewMember);
        reportDataVO.setThisMonthNewMember(thisMonthNewMember);
        reportDataVO.setTotalMember(totalMember);
        reportDataVO.setTodayOrderNumber(todayOrderNumber);
        reportDataVO.setThisWeekOrderNumber(thisWeekOrderNumber);
        reportDataVO.setThisMonthOrderNumber(thisMonthOrderNumber);
        reportDataVO.setHotSetmeal(hotSetmeals);

        return reportDataVO;
    }

    /**
     * 导入运营数据报表
     *
     * @param response
     */
    @Override
    public void exportBusinessData(HttpServletResponse response) {
        try {

            ReportDataVO reportData = getBusinessReportData();

            //1: 读取模板
            InputStream in = this.getClass().getClassLoader().getResourceAsStream("report_template.xlsx");
            // 专门从 类路径下读取 资源文件
            // 流里面的字节变成 excel文件 ？
            XSSFWorkbook excel = new XSSFWorkbook(in);
            //2: 查询数据 写入模板
            //获取 第一个sheet
            XSSFSheet sheet = excel.getSheetAt(0);
            //创建行，0表示第一行
            XSSFRow row = sheet.createRow(0);
            //第二行
            sheet.getRow(2).getCell(5).setCellValue(String.valueOf(reportData.getReportDate()));//日期
            //第四行
            sheet.getRow(4).getCell(5).setCellValue(reportData.getTodayNewMember());//新增会员数（本日）
            sheet.getRow(4).getCell(7).setCellValue(reportData.getTotalMember());//总会员数

            //第五行
            sheet.getRow(5).getCell(5).setCellValue(reportData.getThisWeekNewMember());//本周新增会员数
            sheet.getRow(5).getCell(7).setCellValue(reportData.getThisMonthNewMember());//本月新增会员数

            //第七行
            sheet.getRow(7).getCell(5).setCellValue(reportData.getTodayOrderNumber());//今日预约数
            sheet.getRow(7).getCell(7).setCellValue(reportData.getTodayVisitsNumber());//今日到诊数

            //第八行
            sheet.getRow(8).getCell(5).setCellValue(reportData.getThisWeekOrderNumber());//本周预约数
            sheet.getRow(8).getCell(7).setCellValue(reportData.getThisWeekVisitsNumber());//本周到诊数

            //第九行
            sheet.getRow(9).getCell(5).setCellValue(reportData.getThisMonthOrderNumber());//本月预约数
            sheet.getRow(9).getCell(7).setCellValue(reportData.getThisMonthVisitsNumber());//本月到诊数





            //获取最后一行
            int lastRowNum = sheet.getLastRowNum();
            List<HotSetmeal> hotSetmeal = reportData.getHotSetmeal();
            for (int i = 12; i<=lastRowNum; i++) {


                for (int i1 = 0; i1 < hotSetmeal.size(); i1++) {


                    sheet.getRow(i).getCell(4).setCellValue(hotSetmeal.get(i1).getName());//套餐名称
                    sheet.getRow(i).getCell(5).setCellValue(hotSetmeal.get(i1).getSetmeal_count());//预约数量
                    sheet.getRow(i).getCell(6).setCellValue(hotSetmeal.get(i1).getProportion());//占比

                }

            }

            response.setContentType("application/vnd.ms-excel");
            response.setHeader("content-Disposition", "attachment;fileName=" + reportData.getReportDate() + "_report.xlsx");

            //3: 导出模板
            // 通过response 对象获取字节输出流  通过excel方法写到浏览器上
            ServletOutputStream out = response.getOutputStream();
            excel.write(out);

            //释放资源
            out.flush();
            out.close();
            excel.close();


        } catch (Exception e) {
            System.out.println("您读取模板有问题，它不是excel文件...");
            throw new RuntimeException("程序飞走了");
        }


    }

}
